package org.jimmy.tang.ehcache.better;

import org.jimmy.tang.ehcache.Account;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;

/**
 * @author jimmy
 * 
 */
public class AccountService {

    /**
     * 如果对象的方法是内部调用（即 this 引用）而不是外部引用，则会导致 proxy 失效，那么我们的切面就失效，也就是说上面定义的各种注释包括
     * ,@Cacheable、@CachePut 和 @CacheEvict 都会失效
     * @param userName
     * @return
     */
    public Account getAccountByName2(String userName) {
        return getAccountByName(userName);
    }

    @Cacheable(value = "accountCache")
    // @Cacheable(value = "accountCache", condition = "#userName.length() <= 4")
    public Account getAccountByName(String userName) {
        // 方法内部实现不考虑缓存逻辑，直接实现业务

        return getFromDB(userName);
    }

    @Cacheable(value = "accountCache", key = "#userName.concat(#password)")
    public Account getAccount(String userName, String password, boolean sendLog) {
        // 方法内部实现不考虑缓存逻辑，直接实现业务
        return getFromDB(userName, password);

    }

    @CachePut(value = "accountCache", key = "#account.getName()")
    // 更新 accountCache 缓存
    public Account updateAccount1(Account account) {
        return updateDB(account);
    }

    @CacheEvict(value = "accountCache", key = "#account.getName()")
    // 清空 accountCache 缓存
    public void updateAccount(Account account) {

        updateDB(account);
    }

    @CacheEvict(value = "accountCache", allEntries = true)
    // 清空 accountCache 缓存
    public void reload() {

    }

    @CacheEvict(value = "accountCache", allEntries = true)
    // 该方法执行失败，缓存不会被清空
    public void reload1() {
        throw new RuntimeException();
    }

    @CacheEvict(value = "accountCache", allEntries = true, beforeInvocation = true)
    // 清空 accountCache 缓存
    public void reload2() {
        throw new RuntimeException();
    }

    private Account getFromDB(String acctName) {
        System.out.println("real querying db..." + acctName);
        return new Account(acctName);
    }

    private Account getFromDB(String acctName, String password) {
        System.out.println("real querying db with password..." + acctName);
        return new Account(acctName);
    }

    private Account updateDB(Account account) {
        System.out.println("real update db..." + account.getName());
        return account;
    }

}
